package Experiment2;

import edu.princeton.cs.algs4.*;
import java.util.*;
import java.nio.file.*;

public class Experiment {

    private Integer data[];
    private long results_time[][];
    private long results_space[][];
    private long average_time[];
    private long average_space[];
    private String dataset_name;

    //初始化实验数据
    public Experiment(){
        
        
        List<Integer> data_list=new ArrayList<Integer>();

        try{
            System.out.print("输入使用的数据集文件名：");
            
            Scanner terminal_sc=new Scanner(System.in);
            dataset_name=terminal_sc.nextLine();

            Path path=Paths.get(".\\src\\Experiment2\\"+dataset_name);
            Scanner dataset_sc=new Scanner(path.toFile());

            
            while(dataset_sc.hasNextInt()){
                data_list.add(dataset_sc.nextInt());
            }

        }catch(Exception e){
            System.out.println(e);
            
        }

        this.data=new Integer[data_list.size()];
        data_list.toArray(this.data);

        results_time=new long[5][10];
        results_space=new long[5][10];
        average_time=new long[5];
        average_space=new long[5];
    }

    //运行实验
    public void RunExperiment(){
        int sort_i=0;
        
        for(sort_i=0;sort_i<5;sort_i++){
            long total_time=0;
            long total_space=0;
            for(int t=0;t<10;t++){
                Integer data_for_run[]=Arrays.copyOfRange(data,0, data.length);
                ResultPerRun res=RunSort(data_for_run, sort_i+1);
                results_time[sort_i][t]=res.GetTimecost();
                total_time+=res.GetTimecost();
                results_space[sort_i][t]=res.GetSpacecost();
                total_space+=res.GetSpacecost();
            } 
            average_time[sort_i]=total_time/10;
            average_space[sort_i]=total_space/10;
        }
        System.out.println("输入数据集："+dataset_name+"已完成实验");
    }

    //运行一次输入中的一次排序
    private ResultPerRun RunSort(Integer data[],int sort_type){
        long timecost=0;
        long spacecost=0;
        Runtime runtime=Runtime.getRuntime();
        
        long start_t=0,total_mem=0,free_mem=0,end_t=0;
        switch (sort_type) {
            case 1:
                runtime.gc();
                start_t=System.nanoTime();
                total_mem=runtime.totalMemory();
                Insertion.sort(data);
                free_mem=runtime.freeMemory();
                end_t=System.nanoTime();
                break;
            case 2:
                runtime.gc();
                start_t=System.nanoTime();
                total_mem=runtime.totalMemory();
                Merge.sort(data);
                free_mem=runtime.freeMemory();
                end_t=System.nanoTime();
                break;
            case 3:
                runtime.gc();
                start_t=System.nanoTime();
                total_mem=runtime.totalMemory();
                MergeBU.sort(data);
                free_mem=runtime.freeMemory();
                end_t=System.nanoTime();
                break;
            case 4:
                runtime.gc();
                start_t=System.nanoTime();
                total_mem=runtime.totalMemory();
                Quick.sort(data);
                free_mem=runtime.freeMemory();
                end_t=System.nanoTime();
                break;
            case 5:
                runtime.gc();
                start_t=System.nanoTime();
                total_mem=runtime.totalMemory();
                Quick3way.sort(data);
                free_mem=runtime.freeMemory();
                end_t=System.nanoTime();
                break;
            default:
                break;
        }
        
        timecost=(end_t-start_t)/1000;
        spacecost=(total_mem-free_mem)/1024;

        return new ResultPerRun(timecost, spacecost);
    }

    public void PrintTimeResults(){
        System.out.println("Time Usage/us");
        System.out.printf("\t1\t2\t3\t4\t5\t6\t7\t8\t9\t10\taverage\n");
        for(int sort_i=0;sort_i<5;sort_i++){
            switch (sort_i) {
                case 0: System.out.print("IS"); break;
                case 1: System.out.print("TDM"); break;
                case 2: System.out.print("BUM"); break;
                case 3: System.out.print("RQ"); break;
                case 4: System.out.print("QD3P"); break;
                default: break;
            }

            for (long time : results_time[sort_i]) {
                System.out.print("\t"+time);
            }
            System.out.println("\t"+average_time[sort_i]);
        }
    }

    public void PrintSpaceResults(){
        System.out.println("Space Usage/KB");
        System.out.printf("\t1\t2\t3\t4\t5\t6\t7\t8\t9\t10\taverage\n");
        for(int sort_i=0;sort_i<5;sort_i++){
            switch (sort_i) {
                case 0: System.out.print("IS"); break;
                case 1: System.out.print("TDM"); break;
                case 2: System.out.print("BUM"); break;
                case 3: System.out.print("RQ"); break;
                case 4: System.out.print("QD3P"); break;
                default: break;
            }

            for (long space : results_space[sort_i]) {
                System.out.print("\t"+space);
            }
            System.out.println("\t"+average_space[sort_i]);
        }
    }
    
    public static void main(String[] args){
        Experiment ex=new Experiment();
        ex.RunExperiment();
        ex.PrintTimeResults();
        System.out.println();
        ex.PrintSpaceResults();
    }

}

class ResultPerRun{
    private long timecost; //毫秒
    private long spacecost; //KB
    
    public ResultPerRun(long timecost,long spacecost){
        this.timecost=timecost;
        this.spacecost=spacecost;
    }

    public long GetTimecost(){
        return timecost;
    }

    public long GetSpacecost(){
        return spacecost;
    }
}
